﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Web;
using Alogient.Cameleon.Sdk.Items;

namespace Alogient.Cameleon.Sdk.UrlRewriting
{
    public class URLRewriter : System.Web.IHttpModule
    {
        /// <summary>
        /// Dispose is required from the IHttpModule interface
        /// </summary>
        public virtual void Dispose() { }

        /// <summary>
        /// Init is required from the IHttpModule interface
        /// </summary>
        /// <param name="Appl"></param>
        public virtual void Init(System.Web.HttpApplication Appl)
        {
            // WARNING!  This does not work with Windows authentication!
            // If you are using Windows authentication, change to app.BeginRequest
            //app.AuthorizeRequest += new EventHandler(this.BaseModuleRewriter_AuthorizeRequest);
            //make sure to wire up to BeginRequest
            Appl.AuthorizeRequest += new System.EventHandler(Rewrite_AuthorizeRequest);
            //Appl.BeginRequest += new System.EventHandler(Rewrite_BeginRequest);
        }

        /// <summary>
        /// To handle the starting of the incoming request
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="args"></param>
        protected virtual void Rewrite_AuthorizeRequest(object sender, System.EventArgs args)
        {
            System.Web.HttpApplication Appl = (System.Web.HttpApplication)sender;

            Rewrite(Appl.Request.Path, Appl);
        }

        /// <summary>
        /// To handle the starting of the incoming request
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="args"></param>
        protected virtual void Rewrite_BeginRequest(object sender, System.EventArgs args)
        {
            System.Web.HttpApplication Appl = (System.Web.HttpApplication)sender;

            Rewrite(Appl.Request.Path, Appl);
        }

        protected void Rewrite(string path, System.Web.HttpApplication Appl)
        {
            string culture = string.Empty;
            string formatUrl = "~/{0}?NavId={1}&CultureCode={2}";
            string rewrittenURL = string.Empty;

            RewriterRuleCollection RuleSet = RewritingConfig.GetConfig().RuleSet;

            //Search for the first rule that applies
            foreach (Rule rule in RuleSet)
            {
                //Sets the rule in context (changes ~ for the application path)
                string s = "^" + ResolveUrl(Appl.Context.Request.ApplicationPath, rule.Source) + "$";

                Regex regex = new Regex(s, RegexOptions.IgnoreCase);

                if (regex.IsMatch(path))
                {

                    string queryString = Appl.Request.QueryString.ToString();
                    HttpContext.Current.Items["originalUrl"] = string.Format("{0}?{1}", path, queryString);
                    string appPath = Appl.Request.ApplicationPath;
                    if (appPath.Length > 1)
                        path = path.Remove(0, appPath.Length);
                    string[] parts = path.Split('/');

                    //The culture is the 3rd part of the splitted path
                    if (parts.Length > 0 && parts[1].IndexOf('.') < 0)
                        culture = parts[1];

                    //Get the default culture
                    if (culture == string.Empty)
                        culture = CMSettings.DefaultCultureCode;

                    //Parse the path to obtain each pages parent until the last page, wich we will be showing
                    int parentID = 0;

                    for (int i = 2; i < parts.Length; i++)
                    {
                        string part = parts[i];
                        if (part != null && part != string.Empty && part.Trim().Length > 0)
                        {
                            //CMPageCollection pages = CMServices.SearchFilteredPages(string.Format("ParentID={0} AND PageName='{1}'", parentID.ToString(), part), string.Empty, culture);
                            CMPage page = GetSubpageByName(parentID, culture, part);
                            if (page != null)
                            {
                                parentID = page.NavID;
                            }
                            else if (part.ToLower().IndexOf(".aspx") > 0)
                            {
                                break;
                            }
                            else
                            {
                                //If the page doesn't exist, we must not rewrite to get a 404
                                parentID = -1;
                                break;
                            }
                        }
                    }
                    if (parentID == 0)
                        parentID = CMSettings.DefaultNavID;

                    if (CMServices.PageExists(parentID, culture))
                    {
                        CMPage page = CMServices.GetPage(parentID, culture);
                        rewrittenURL = string.Format(formatUrl, page.TemplateUrl, page.NavID.ToString(), page.CultureCode);

                        if (!string.IsNullOrEmpty(queryString))
                            rewrittenURL = string.Format("{0}&{1}", rewrittenURL, queryString);
                    }
                    break;
                }
            }

            if (!string.IsNullOrEmpty(rewrittenURL))
            {
                Appl.Context.RewritePath(rewrittenURL);
            }

        }

        internal static CMPage GetSubpageByName(int parentID, string cultureCode, string name)
        {
            CMPage parentPage = CMServices.GetPage(parentID, cultureCode);
            CMPageCollection subpages = parentPage.Subpages;
            foreach (CMPage subpage in subpages)
            {
                if (subpage.PageTitle == name)
                    return subpage;
            }

            return null;
        }

        internal static string ResolveUrl(string appPath, string url)
        {
            if (url.Length == 0 || url[0] != '~')
                return url;		// there is no ~ in the first character position, just return the url
            else
            {
                if (url.Length == 1)
                    return appPath;  // there is just the ~ in the URL, return the appPath
                if (url[1] == '/' || url[1] == '\\')
                {
                    // url looks like ~/ or ~\
                    if (appPath.Length > 1)
                        return appPath + "/" + url.Substring(2);
                    else
                        return "/" + url.Substring(2);
                }
                else
                {
                    // url looks like ~something
                    if (appPath.Length > 1)
                        return appPath + "/" + url.Substring(1);
                    else
                        return appPath + url.Substring(1);
                }
            }
        }
    }
}
